﻿using System;
using System.Threading.Tasks;

namespace ObserverDelegate
{
    /// <summary>
    /// 短信观察者
    /// </summary>
    public class MessageObserver
    {
        public ISubject Subject { get; set; }

        public MessageObserver(ISubject subject)
        {
            Subject = subject;
        }

        /// <summary>
        /// 发送短信
        /// </summary>
        /// <returns></returns>
        public Task SendMessageAsync()
        {
            Console.WriteLine($"{Subject.State}:短信通知了...");
            return Task.CompletedTask;
        }
    }

    /// <summary>
    /// 积分观察者
    /// </summary>
    public class BonusObserver
    {
        public ISubject Subject { get; set; }

        public BonusObserver(ISubject subject)
        {
            Subject = subject;
        }

        /// <summary>
        /// 添加积分
        /// </summary>
        /// <returns></returns>
        public Task AddBonusAsync()
        {
            Console.WriteLine($"{Subject.State}:积分增加了...");
            return Task.CompletedTask;
        }
    }

    /// <summary>
    /// 券观察者
    /// </summary>
    public class CouponObserver
    {
        public ISubject Subject { get; set; }

        public CouponObserver(ISubject subject)
        {
            Subject = subject;
        }

        /// <summary>
        /// 制券
        /// </summary>
        /// <returns></returns>
        public async Task MakeCouponAsync()
        {
            Console.WriteLine($"{Subject.State}:开始制券...");
            //模拟制券耗时
            await Task.Delay(3000);
            Console.WriteLine($"{Subject.State}:制券完成...");
        }
    }

    /// <summary>
    /// 抽象通知者
    /// </summary>
    public interface ISubject
    {
        /// <summary>
        /// 通知
        /// </summary>
        /// <returns></returns>
        public Task Notify();

        public string State { get; set; }
    }

    /// <summary>
    /// 支持成功通知者
    /// </summary>
    public class PaySuccessSubject : ISubject
    {
        public Func<Task> Update;

        public string State { get; set; }

        public Task Notify()
        {
            Update();
            return Task.CompletedTask;
        }
    }
}